package cn.kdyzm.twofa.service.impl;

import cn.kdyzm.json.util.JsonUtils;
import cn.kdyzm.twofa.entity.SysUser2fa;
import cn.kdyzm.twofa.mapper.ISysUser2faMapper;
import cn.kdyzm.twofa.mapper.ISysUserMapper;
import cn.kdyzm.twofa.service.ITwoFaService;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.WriterException;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;
import com.warrenstrange.googleauth.*;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;

/**
 * @author kdyzm
 * @date 2025/6/16
 */
@Slf4j
@Service
@AllArgsConstructor
public class TwoFaServiceImpl implements ITwoFaService {

    private final ISysUserMapper sysUserMapper;

    private final ICredentialRepository credentialRepository;

    private final ISysUser2faMapper sysUser2faMapper;

    private static final String ISSUER = "一枝梅的博客";

    @Override
    public String generateSecretKey() {
        GoogleAuthenticator gAuth = new GoogleAuthenticator();
        final GoogleAuthenticatorKey key = gAuth.createCredentials();
        log.info(JsonUtils.toPrettyString(key));
        return key.getKey();
    }

    @Override
    public String generateOptAuthUrl(String userName) {
        GoogleAuthenticator gAuth = getGoogleAuthenticator();
        final GoogleAuthenticatorKey key = gAuth.createCredentials(userName);
        return GoogleAuthenticatorQRGenerator.getOtpAuthURL(
                ISSUER,
                userName,
                key
        );
    }

    private GoogleAuthenticator getGoogleAuthenticator() {
        GoogleAuthenticatorConfig config = new GoogleAuthenticatorConfig
                .GoogleAuthenticatorConfigBuilder()
                //设置容忍度最小
                .setWindowSize(1)
                .build();
        GoogleAuthenticator gAuth = new GoogleAuthenticator(config);
        gAuth.setCredentialRepository(credentialRepository);
        return gAuth;
    }

    @Override
    public ByteArrayOutputStream generateOptAuthPicByteArray(String userName) throws WriterException, IOException {
        GoogleAuthenticator googleAuthenticator = getGoogleAuthenticator();
        GoogleAuthenticatorKey credentials = googleAuthenticator.createCredentials(userName);
        String otpAuthTotpURL = GoogleAuthenticatorQRGenerator.getOtpAuthTotpURL(
                ISSUER,
                userName,
                credentials
        );
        QRCodeWriter qrWriter = new QRCodeWriter();
        BitMatrix bitMatrix = qrWriter.encode(otpAuthTotpURL, BarcodeFormat.QR_CODE, 200, 200);
        BufferedImage bufferedImage = MatrixToImageWriter.toBufferedImage(bitMatrix);
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        ImageIO.write(bufferedImage, "png", outputStream);
        return outputStream;
    }

    @Override
    public Boolean checkCode(String userName, Integer code) {
        GoogleAuthenticator gAuth = getGoogleAuthenticator();
        return gAuth.authorizeUser(userName, code);
    }

    @Override
    public String checkFirstCode(Long userId, Integer code) {
        GoogleAuthenticator gAuth = getGoogleAuthenticator();
        SysUser2fa sysUser2fa = sysUser2faMapper.selectByUserId(userId);
        if (gAuth.authorize(sysUser2fa.getSecretKey(), code)) {
            return sysUser2fa.getSecretKey();
        }
        return null;
    }
}
